#include "bsp_clk.h"

void clk_init(void)
{
    CCM->CCGR0 = 0xFFFFFFFF;
    CCM->CCGR1 = 0xFFFFFFFF;
    CCM->CCGR2 = 0xFFFFFFFF;
    CCM->CCGR3 = 0xFFFFFFFF;
    CCM->CCGR4 = 0xFFFFFFFF;
    CCM->CCGR5 = 0xFFFFFFFF;
    CCM->CCGR6 = 0xFFFFFFFF;
}

/* 初始化时钟 */
void imx6u_clkinit(void)
{
	unsigned int reg = 0;

	/* 初始化 IMX6U 的主频为528MHz */
	if(((CCM->CCSR >> 2) & 0x1) == 0){				/* 判断PLL1_SW_CLK_SEL位为0，当前使用 pll1_main_clk */
		CCM->CCSR &= ~(1<<8);						/* 设置CCM_CCSR STEP_SEL位，0 step_clk 选择 osc_clk 24MHz晶振 */
		CCM->CCSR |= (1<<2);						/* 设置PLL1_SW_CLK_SEL位为1，pll1_sw_clk切换到step_clk */
	}

	/* 设置PLL1为1056MHz */
	CCM_ANALOG->PLL_ARM |= (1 << 12);				/* 设置ANANLOG_PLL_ARM bit[12]，power-down PLL1 关闭 pll1_main_clk */
	CCM_ANALOG->PLL_ARM &= ~0x7f;					/* 清零ANANLOG_PLL_ARM bit[6:0] */
	CCM_ANALOG->PLL_ARM |= ((88 << 0) & 0x7f);		/* 设置ANANLOG_PLL_ARM bit[6:0], PLL1 freq=24MHz*88/2=1056Mhz */
	CCM_ANALOG->PLL_ARM |= (1 << 13);				/* 设置ANANLOG_PLL_ARM bit[13] Enable=1, 开启 pll1_main_cl */
	//CCM_ANALOG->PLL_ARM |= ((58 << 0) & 0x7f);	/* 设置ANANLOG_PLL_ARM bit[6:0], PLL1 freq=24MHz*58/2=696Mhz */
	CCM_ANALOG->PLL_ARM &= ~(1 << 12);				/* 清零ANANLOG_PLL_ARM bit[12]，power-up PLL1 关闭 pll1_main_clk */

	CCM->CCSR &= ~(1<<2);							/* pll1_sw_clk切换回pll1_main_clk(PLL1)*/
	
	/* PLL1 frq =24MHz*88/2=1056Mhz */
	/* 设置PLL1 2分频， 1056Mhz/2=528MHz */
	CCM->CACRR = 0x1;							/* ARM_PODF divide by 2 */
							
	/* PLL1 frq =24MHz*58/2=696Mhz */
	/* 设置PLL1 2分频， 696Mhz/1=696Mhz */
	//CCM->CACRR = 0x0;							/* ARM_PODF divide by 1 */


	/* ARM_PODF_BUSY 指示握手是否完成。这一行必须删除掉因为PLL1_ROOT不需要等待握手完成,加上这一句就会子啊这里死循环等待*/
	//while((CCM->CDHIPR & (1<<16)));

	
	//PLL2, System_PLL, PLL2_PFD0~PLL2_PFD3
	reg = CCM_ANALOG->PFD_528;
	reg  &= ~(0x3f3f3f3f);		/* 清零PFD0~PFD3 FRAC */
	reg  |= (27U << 0);			/* PLL2_PFD0_FRAC=27 352MHz */
	reg  |= (16U << 8);			/* PLL2_PFD1_FRAC=16 594MHz */
	reg  |= (24U << 16);		/* PLL2_PFD2_FRAC=24 396MHz */
	reg  |= (32U << 24);		/* PLL2_PFD3_FRAC=32 297MHz */
	CCM_ANALOG->PFD_528 = reg;


	//PLL3, USB1_PLL, 	PLL3_PFD0~PLL3_PFD3
	reg = CCM_ANALOG->PFD_480;
	reg &= ~(0x3f3f3f3f);		/* 清零PFD0~PFD3 FRAC */
	reg |= (12U << 0);			/* PLL3_PFD0_FRAC=12 352MHz */
	reg |= (16U << 8);			/* PLL3_PFD1_FRAC=16 594MHz */
	reg |= (17U << 16);			/* PLL3_PFD2_FRAC=17 396MHz */
	reg |= (19U << 24);			/* PLL3_PFD3_FRAC=19 200MHz */
	CCM_ANALOG->PFD_480 = reg;


	/* AHB_CLK_ROOT 配置 */
	CCM->CBCMR &= ~(3 << 18);				/* PER_PERIPH_CLK_SEL位清零 */
	CCM->CBCMR |= (1 << 18);				/* PER_PERIPH_CLK_SEL=01, per_periph_clk=PLL2_PFD2=396Mhz */
	CCM->CBCDR &= ~(1 << 25);				/* PER_PERIPH_CLK_SEL位清零, 选择PLL2 pll2_main_clk */
	while((CCM->CDHIPR & (1 << 5)));		/* PERIPH_CLK_SEL_BUSY 指示握手是否完成 */

	/* 正点原子在示例源码和视频教程里都说，此处需要先关闭 AHB_ROOT_CLK 输出，否则时钟设置会出错 */
#if 0
	CCM->CBCDR &= ~(7 << 10);				/* AHB PODF位清零 */
	CCM->CBCDR |= (2 << 10);				/* AHB PODF=010, 3分频，AHB_CLK_ROOT=periph_clk/3=396/3=132MHz */

	//AHB_PODF_BUSY
	while((CCM->CDHIPR & (1 << 1)));		/* AHB_PODF_BUSY 指示握手是否完成 */
#endif

	/* IPG_CLK_ROOT 配置 */
	CCM->CBCDR &= ~(3 << 8);				/* IPG_PODF清零 */
	CCM->CBCDR |= (1 << 8);					/* IPG_PODF=1, 2分频， IPG_CLK_ROOT=AHB_CLK_ROOT/2=132/2=66MHz */
											/* 修改IPG_PODF后，开启IPG_CLK_ROOT 输出*/

	/* PERCLK_CLK_ROOT 配置 */
	CCM->CSCMR1 &= ~(1 << 6);				/* PERCLK_CLK_SEL清零, PERCLK_ROOT选择IPG_CLK_ROOT */
	CCM->CSCMR1 &= ~(0x3f);					/* PERCLK_CLK_PODF清零 */
	CCM->CSCMR1 |= (0x0);					/* PERCLK_CLK_PODF=0, 1分频，PERCLK_ROOT=IPG_CLK_ROOT/1=66MHz */

}
